package gui;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;

import javax.swing.*;

import algoritmi.Algoritam;
import algoritmi.FIFO;
import algoritmi.InformacijeOJednomKoraku;
import algoritmi.LFU;
import algoritmi.LRU;
import algoritmi.Optimalni;

import algoritmi.RandomAlg;
import algoritmi.Ucitavanje;

import anim.Animator;
import anim.InfoListener;

/**
 * @author Marija Prokopijevic
 */

public class GlavniProzor extends JFrame implements InfoListener{
	private static final long serialVersionUID = 1L;
	private JPanel glavniPanel;
	private JPanel pomocniPanel;
	private JPanel dugmadPanel;
	private RucniUnosPanel panelZaUnos;

	private JMenuBar meniTraka;
	private JMenu fileMeni, podesavanjaMeni, algoritmiMeni;//, opsteStrukture;
	private JMenuItem velicinaKesa, velicinaMemorije;
	private JRadioButton[] odabirUnosa = new JRadioButton[3];
	private JRadioButtonMenuItem[] algoritmi = new JRadioButtonMenuItem[5];
	private AlgoritamEnum[] alg = AlgoritamEnum.values();
	
	private JLabel nacinUnosaLabel;
	private JLabel odabraniAlgoritam;
	private JLabel brPogodaka;
	private JLabel brPromasaja;
	
	private JButton pocni, pauza;
	
	private Canvas canvas;
	private Animator animator;
	private Algoritam algoritam = null;
	private AlgoritamEnum toStringAlg;
	private ArrayList<InformacijeOJednomKoraku> koraci = null;
	private Ucitavanje ucitavanje;
	private NacinUnosa nacinUnosa = NacinUnosa.RANDOM;
	
	
	private int memorija = 10;
	private int kes = 5;
	private int lokalnost = 2;
	private JMenuItem novaAnimacija;
	private JMenuItem fifo;
	private JMenuItem lifo;
	private JMenu opsteStrukture;
	
	private enum Mod { Kes, Strukture };
	private Mod mod = Mod.Kes;
	
	public GlavniProzor()
	{
		super("Vizuelizacija algoritama");
		setLookAndFeel();
		
		postaviPanel();
		
		postaviMenije();
		
		postaviDugmad();
		
		this.setSize(450, 500);
		this.setPreferredSize(new Dimension(450, 500));
		Dimension dimenzijeEkrana = Toolkit.getDefaultToolkit().getScreenSize();
		Dimension dimenzijeProzora = this.getSize();
		
		int sirinaProzora = dimenzijeEkrana.width/2 - dimenzijeProzora.width/2;
		int visinaProzora = dimenzijeEkrana.height/2 - dimenzijeProzora.height/2;
		this.setLocation(new Point(sirinaProzora, visinaProzora));
		this.setLayout(new FlowLayout());
		this.pack();
		this.setDefaultCloseOperation(EXIT_ON_CLOSE);
		this.setVisible(true);
		
		dodajDogadjajDugmetu();
		
	}
	
	private void dodajDogadjajDugmetu() {
		animator = new Animator(500, 300);
		animator.dodajInfoListener(this);
		canvas = animator.getCanvas();
		glavniPanel.add(canvas);
		animator.init();
	
		class Osluskivac implements ActionListener{ 
			@Override
			public void actionPerformed(ActionEvent e){				
				panelZaUnos.setVisible(false);
				
				if(algoritam == null){
					toStringAlg = AlgoritamEnum.RANDOM;
					algoritam =  new RandomAlg();
				}
				ucitavanje = new Ucitavanje(memorija, memorija, lokalnost, nacinUnosa);
				algoritam.setIzvorPodataka(ucitavanje);
				algoritam.postaviVelicinuKesa(kes);
				algoritam.postaviVelicinuGlavneMemorije(memorija);
				
				
				if(koraci == null && mod == Mod.Kes)
				{
					if(algoritam == null) return;
					anim.adapter.KoraciUAnimaciju.konvertuj(animator, algoritam.getKoraci(), kes, memorija);
				}
				pomocniPanel.setVisible(false);
				animator.kreni();
				
				odabraniAlgoritam.setText(toStringAlg.toString() +  " algoritam");
				
				pocni.setEnabled(false);
				novaAnimacija.setEnabled(false);
			}
		}
		Osluskivac osluskivac = new Osluskivac();
		pocni.addActionListener(osluskivac);
		novaAnimacija.addActionListener(osluskivac);
		
		pauza.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				animator.setPauza(!animator.getPauza());
				if(pauza.getText().equals("Pauza")){
					pauza.setText("Nastavi");
				}
				else pauza.setText("Pauza");
			}

		});
		
		
	}

	private void postaviPanel() {
		glavniPanel = new JPanel();
		
		glavniPanel.setPreferredSize(new Dimension(370, 400));
		this.add(glavniPanel, BorderLayout.NORTH);
		
		pomocniPanel = new JPanel();
		pomocniPanel.setPreferredSize(new Dimension(360, 60));
		glavniPanel.add(pomocniPanel);
		nacinUnosaLabel = new JLabel("    Odaberite nacin na koji zelite da podaci budu uneseni              ");
		pomocniPanel.add(nacinUnosaLabel);
		panelZaUnos = new RucniUnosPanel(10);
		panelZaUnos.setVisible(false);
		
		ButtonGroup grupa = new ButtonGroup();
		NacinUnosa[] nacini = NacinUnosa.values();
		for(int i = 0; i < 3; i++)
		{
			odabirUnosa[i] = new JRadioButton(nacini[i].toString());
			pomocniPanel.add(odabirUnosa[i]);
			grupa.add(odabirUnosa[i]);
		}
		glavniPanel.add(panelZaUnos);
		odabirUnosa[2].setSelected(true);
		odabirUnosa[0].addActionListener(new ActionListener(){
			@Override
			public void actionPerformed(ActionEvent e) {
				nacinUnosa = NacinUnosa.RANDOM;
				panelZaUnos.setVisible(false);
			}
		});
		odabirUnosa[1].addActionListener(new ActionListener(){
			@Override
			public void actionPerformed(ActionEvent e) {
				panelZaUnos.setVisible(true);
				nacinUnosa = NacinUnosa.RUCNI;
				
			}
		});
		odabirUnosa[2].addActionListener(new ActionListener(){
			@Override
			public void actionPerformed(ActionEvent e) {
				nacinUnosa = NacinUnosa.FAJL;
				panelZaUnos.setVisible(false);
			}
			
		});
	}

	private void postaviDugmad() {
		dugmadPanel = new JPanel();
		
		pocni = new JButton("Pocni");
		dugmadPanel.add(pocni);
		
		pauza = new JButton("Pauza");
		dugmadPanel.add(pauza);
		
		this.add(dugmadPanel, BorderLayout.SOUTH);
		
		brPogodaka = new JLabel("  Broj pogodaka : 0  ");
		brPromasaja = new JLabel("  Broj promasaja : 0  ");
		odabraniAlgoritam = new JLabel("Algoritam nije odabran");
		glavniPanel.add(odabraniAlgoritam);
		glavniPanel.add(brPogodaka);
		glavniPanel.add(brPromasaja);
	}

	private void postaviMenije() {
		meniTraka = new JMenuBar();
		this.setJMenuBar(meniTraka);
		
		fileMeni = new JMenu("File");
		meniTraka.add(fileMeni);
		
		AbstractAction izlaz = new AbstractAction(){
			private static final long serialVersionUID = 1L;
			@Override
			public void actionPerformed(ActionEvent e) {
				System.exit(0);	
			}
		};
		izlaz.putValue(Action.NAME, "Izlaz");
		izlaz.putValue(Action.SMALL_ICON, new ImageIcon("exit.png"));
		
		novaAnimacija = new JMenuItem("Nova animacija");
		novaAnimacija.setIcon(new ImageIcon("maca.png"));
		
		fileMeni.add(novaAnimacija);
		fileMeni.addSeparator();
		fileMeni.add(izlaz);
		
		podesavanjaMeni = new JMenu("Podesavanja");
		meniTraka.add(podesavanjaMeni);
		
		velicinaKesa = new JMenuItem("Kes");
		velicinaKesa.setIcon(new ImageIcon("kes.png"));
		velicinaKesa.addActionListener(new ActionListener(){
			
			@Override
			public void actionPerformed(ActionEvent e) {
				String inputValue = JOptionPane.showInputDialog("Velicina kes memorije:");
				if(inputValue != null && !inputValue.equals(""))
					kes = Integer.parseInt(inputValue);
				koraci = null;
			}			
		});
		velicinaMemorije = new JMenuItem("Memorija");
		velicinaMemorije.setIcon(new ImageIcon("memorija.png"));
		velicinaMemorije.addActionListener(new ActionListener(){

			@Override
			public void actionPerformed(ActionEvent e) {
				String inputValue = JOptionPane.showInputDialog("Velicina glavne memorije:");
				if(inputValue != null && !inputValue.equals(""))
					memorija = Integer.parseInt(inputValue);
				
				koraci = null;
			}
			
		});
		
		JMenuItem lokalnostItem = new JMenuItem("Lokalnost");
		lokalnostItem.addActionListener(new ActionListener(){
			@Override
			public void actionPerformed(ActionEvent e) {
				String inputValue = JOptionPane.showInputDialog("Lokalnost:");
				if(inputValue != null && !inputValue.equals(""))
					lokalnost = Integer.parseInt(inputValue);
				koraci = null;
			}
			
		});
		
		podesavanjaMeni.add(velicinaKesa);
		podesavanjaMeni.add(velicinaMemorije);
		podesavanjaMeni.add(lokalnostItem);
		
		opsteStrukture = new JMenu("Opste strukture");
		meniTraka.add(opsteStrukture);	
		ButtonGroup pupi = new ButtonGroup();
		
		fifo = new JRadioButtonMenuItem("Red (FIFO)");
		opsteStrukture.add(fifo);
		fifo.addActionListener(new ActionListener(){

			@Override
			public void actionPerformed(ActionEvent e) {
				anim.adapter.KoraciUAnimaciju.generisiQueueAnimaciju(animator);
				mod = Mod.Strukture;
			}
			
		});
		
		lifo = new JRadioButtonMenuItem("Stek (LIFO)");
		lifo.addActionListener(new ActionListener(){

			@Override
			public void actionPerformed(ActionEvent e) {
				anim.adapter.KoraciUAnimaciju.generisiStackAnimaciju(animator);
				mod = Mod.Strukture;
			}
			
		});
		opsteStrukture.add(lifo);
		
		pupi.add(fifo);
		pupi.add(lifo);
		
		algoritmiMeni = new JMenu("Algoritmi");
		meniTraka.add(algoritmiMeni);
		
		ButtonGroup grupaAlgoritama = new ButtonGroup();
		for(int i = 0; i < 5; i++)
		{
			algoritmi[i] = new JRadioButtonMenuItem(alg[i].toString());
			grupaAlgoritama.add(algoritmi[i]);
			algoritmiMeni.add(algoritmi[i]);
		}
		
		
		
		algoritmi[0].addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				toStringAlg = AlgoritamEnum.LRU;
				algoritam = new LRU();
				koraci = null;
				mod = Mod.Kes;
			}
		});
		
		algoritmi[1].addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				toStringAlg = AlgoritamEnum.LFU;
				algoritam = new LFU();
				koraci = null;
				mod = Mod.Kes;
			}
		});
		
		algoritmi[2].addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				toStringAlg = AlgoritamEnum.FIFO;
				algoritam = new FIFO();
				koraci = null;
				mod = Mod.Kes;
			}
		});
		
		algoritmi[3].addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				toStringAlg = AlgoritamEnum.OPTIMALNI;
				algoritam = new Optimalni();
				koraci = null;
				mod = Mod.Kes;
			}
		});
		algoritmi[4].setSelected(true);
		algoritmi[4].addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				toStringAlg = AlgoritamEnum.RANDOM;
				algoritam = new RandomAlg();
				koraci = null;
				mod = Mod.Kes;
			}
		});
		
		
		
	}
	
	@SuppressWarnings("unused")
	private void resetujAnimaciju()
	{
		if(algoritam == null) return;
		anim.adapter.KoraciUAnimaciju.konvertuj(animator, algoritam.getKoraci(), kes, memorija);
	}

	private void setLookAndFeel() {
		try {
			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (UnsupportedLookAndFeelException e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
		new GlavniProzor();
	}

	@Override
	public void osvjeziInformacije(int brPog, int brProm) {
		brPogodaka.setText("  Broj pogodaka : " + brPog + "  ");
		brPromasaja.setText("  Broj promasaja : " + brProm + "  ");
		
	}

	@Override
	public void animacijaZavrsena() {
		pocni.setEnabled(true);
		novaAnimacija.setEnabled(true);
	}
}
